#ifndef _NETDEV_H
#define _NETDEV_H

#ifdef __cplusplus
extern "C" {
#endif

#include <net/ethernet.h>
#include <net/socket.h>
#include <net/udp.h>
#include <net/tcp.h>
#include <net/arp.h>
#include <net/ip.h>

struct s_net_buff_arp
{
	int need;                  // set if ARP needed
	unsigned int addr;         // protocol address for ARP
};

struct s_net_buff
{
	struct s_net_buff* next;

	struct s_net_device *dev;

	unsigned char* data;
	unsigned char* rowdata;
	unsigned int   data_length;

	unsigned int size;

	unsigned int pa_addr;

	struct s_net_buff_arp arp;

	struct s_ethhdr *eth;
	struct s_socket *socket;
	struct s_sockaddr_in *sa_daddr;

	unsigned int csum;

	unsigned int retransmittimer;
	unsigned int retransmits;
};

struct s_net_device
{
	unsigned char name[20];
	unsigned short ioaddr;
	unsigned short irq;

	unsigned char tx_lock;

	unsigned short if_port;
	unsigned int mode;            // 1 = loopback mode

	unsigned char ha_len;
	unsigned char pa_len;

	unsigned char dev_addr[7];


	unsigned int pa_addr;

	unsigned int pa_gateway;      // Standard GATEWAY IP Address

	struct enet_statistics stats;

	void *priv;

	int (*open)(struct s_net_device *dev);
	int (*stop)(struct s_net_device *dev);

	unsigned int major;           // major device pid for network device
};

/**************************** Net devices ****************************/
int register_netdev(unsigned char*name, int pid);

/************************************************************************/
/* Functions to swap bytes of a short integer
/************************************************************************/
static inline unsigned short int htons(unsigned short int x)
{
#ifdef __i386__
	asm volatile ("xchgb %b0,%h0"		/* swap bytes		*/
		: "=q" (x)
		:  "0" (x));
#endif
	return x;
}

static inline unsigned short int ntohs(unsigned short int x)
{
#ifdef __i386__
	asm volatile("xchgb %b0,%h0"		/* swap bytes		*/
		: "=q" (x)
		:  "0" (x));
#endif
	return x;
}

static inline unsigned int htonl(unsigned long int x)
{
#ifdef __i386__
	asm volatile("xchgb %b0,%h0\n\t"	/* swap lower bytes*/
			"rorl $16,%0\n\t"			/* swap words*/
			"xchgb %b0,%h0"				/* swap higher bytes*/
			:"=q" (x)
			: "0" (x));
#endif
	return x;
}

static inline unsigned long int ntohl(unsigned long int x)
{
#ifdef __i386__
	asm volatile ("bswap %0" : "=r" (x) : "0" (x));
#endif
	return x;
}


void icmp_rcv(struct s_net_buff *buff, struct s_net_device *dev);


void write_netdev(unsigned int major, struct s_net_buff *buff);

/* Display an Ethernet address in readable format. */
char *eth_print(unsigned char *ptr);
void eth_build_header(struct s_net_buff *buff, struct s_net_device *dev, unsigned char* daddr, unsigned short proto);

//3c509
int el3_start_xmit(struct s_net_device *dev, struct s_net_buff* buff);

#ifdef __cplusplus
}
#endif

#endif